/**
 * Copyright (c) 2010-2011 julewa.com.  
 * All rights reserved. 
 * 
 * @author Huang Benhua
 * @date 2011-7-20
 * 
**/
package com.julewa.db;

import java.util.Collection;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import com.julewa.Texts;
import com.julewa.db.BeanInfo.ColumnInfo;
import com.julewa.loading.ClientImpl;

public class BeanValidator {
	private @Autowired ClientImpl client;
	private @Autowired DB db;
	private @Autowired Texts texts;
	
	public BeanInfo getBeanInfo(String type){
		return db.getBeanInfo(type);
	}
	
	public BeanInfo getBeanInfo(Class<?> clazz){
		return db.getBeanInfo(clazz);
	}
	
	public boolean checkColumn(String prefix, Object bean, String column){
		return checkColumn(prefix, bean, getBeanInfo(bean.getClass()).getColumn(column));
	}
	
	public boolean checkKeys(String prefix, Object bean){
		return checkColumns(prefix, bean, getBeanInfo(bean.getClass()).getKeys());
	}
	
	public boolean checkColumns(String prefix, Object bean){
		return checkColumns(prefix, bean, getBeanInfo(bean.getClass()).getColumns());
	}
	
	public boolean checkAllColumns(String prefix, Object bean){
		return checkColumns(prefix, bean, getBeanInfo(bean.getClass()).getAllColumns());
	}
	
	public boolean checkColumn(String prefix, Object bean, ColumnInfo column){
		return _checkBeanState(client.getFieldErrors(), prefix, bean, column);
	};
	public boolean checkColumns(String prefix, Object bean, Collection<ColumnInfo> columns){
		Map<String, String> errors = client.getFieldErrors();
		prefix += ".";
		for(ColumnInfo c:columns){
			_checkBeanState(errors, prefix, bean, c);
		}
		return errors.isEmpty();
	};
	
	public boolean checkField(String field, String label, String value, Integer lenMin, Integer lenMax){
		return setState(field, label, getState(value, lenMin, lenMax));
	}
	public boolean checkField(String field, String label, String value, Integer lenMax){
		return setState(field, label, getState(value, lenMax));
	}
	public <T extends Comparable<T>> boolean checkField(String field, String label, T value, T min, T max){
		return setState(field, label, getState(value, min, max));
	}
	
	public boolean checkField(String field, String value, Integer lenMin, Integer lenMax){
		return setState(field, texts.findLabel(field), getState(value, lenMin, lenMax));
	}
	public boolean checkField(String field, String value, Integer lenMax){
		return setState(field, texts.findLabel(field), getState(value, lenMax));
	}
	public <T extends Comparable<T>> boolean checkField(String field, T value, T min, T max){
		return setState(field, texts.findLabel(field), getState(value, min, max));
	}
	
	//////////////////
	public boolean setState(String field, String label, DataState state){
		return _setErrorState(client.getFieldErrors(), field, label, state);
	};
	public static final DataState getState(String value, Integer lenMin, Integer lenMax){
		if(value == null){
			if(lenMin == null)return DataState.NORMAL;
			return DataState.IS_NULL;
		}
		value = value.trim();
		if(lenMin != null && value.length() < lenMin){
			if(value.length() < 1){
				return DataState.IS_EMPTY;
			}else{
				return DataState.TOO_SHORT;
			}
		}
		if(lenMax != null && value.length() > lenMax){ 
			return DataState.OVER_SIZE;
		}
		return DataState.NORMAL;
	}
	
	public static final DataState getState(String value, Integer lenMax){
		return getState(value, 1, lenMax);
	}
	
	public static final <T extends Comparable<T>> DataState getState(T value, T min, T max){
		if(value == null){
			if(min == null)return DataState.NORMAL;
			return DataState.IS_NULL;
		}
		if(min != null && value.compareTo(min) > 0){
			return DataState.TOO_SMALL;
		}
		if(max != null && value.compareTo(max) < 0){
			return DataState.TOO_BIG;
		}
		return DataState.NORMAL;
	};
	
	
	/////////////////////////////
	//TODO 或许需要改成配置方式
	private boolean _setErrorState(Map<String, String> errors, String field, String label, DataState state){
		switch(state){
			case NORMAL: return true;
			case IS_NULL:	errors.put(field, label + "为空");break;
			case TOO_SMALL:	errors.put(field, label + "太小");break;
			case TOO_BIG:	errors.put(field, label + "太大");break;
			case IS_EMPTY:	errors.put(field, label + "不能为空");break;
			case TOO_SHORT:	errors.put(field, label + "太短");break;
			case OVER_SIZE:	errors.put(field, label + "太长");break;
			case ERROR_FORMAT:errors.put(field, label + "格式错误");break;
		}
		return false;
	}
	private boolean _checkBeanState(Map<String, String> errors, String prefix, Object bean, ColumnInfo column){
		DataState s = column.checkDataState(bean);
		if(s == null || s.equals(DataState.NORMAL))return true;
		_setErrorState(errors, prefix + column.getCode(), column.getLabel(), s);
		return false;
	}
}
